import * as vscode from 'vscode';
import { CancellationToken, CompletionContext, ExtensionContext, Position, TextDocument } from 'vscode';
import * as ts from "typescript";
import {drop} from 'ramda';
import { extractUrlApiKeyFromFile, extractAPIEndpointKeys } from './utils/apiKeyExtractor';
const convertPath = require('@stdlib/utils-convert-path');

const fs = require('fs');
const os = require('os');

const platform = os.platform();
const isWindows = platform === 'win32';
const canReadFileTypes = ['ts','js','tsx','jsx'];
let innerActions:string[] = (vscode.workspace.getConfiguration('xlogicTips').get('innerActions') as string).split(',');
let actionParams:string = (vscode.workspace.getConfiguration('xlogicTips').get('innerActionParams') as string);
let apiUrlNameList: string[] = [];

let xlogicActionList: string[] = [];


const languagesList = ['html', 'javascript', 'typescript', 'vue'];
function getModuleActionName(fileName:string,storePath?:string,modelName?:string):Array<string>{
  let tsOrJsFilePath = fileName;
  if(storePath){
    tsOrJsFilePath =convertPath(storePath+fileName,isWindows?'win32':'posix');
  }

	const sourceFile = ts.createSourceFile(
		tsOrJsFilePath,
		fs.readFileSync(tsOrJsFilePath).toString(),
		ts.ScriptTarget.ES2015,
		/*setParentNodes */ true
	);
	let exportDefaultAst:any = sourceFile.statements.filter((astItem:ts.Node)=>astItem.kind === ts.SyntaxKind.ExportAssignment)[0];
	let actionList:string[] = [];
	if(exportDefaultAst){
		let actionsNode = exportDefaultAst.expression.properties.filter((node:any) => node.name.escapedText === 'actions' );

		actionsNode[0].initializer.properties.forEach((node:any) => {
			let actionName = node?.name?.escapedText;
			if(actionName){
				actionList.push(modelName ? `${modelName}/${actionName}` : actionName);
        return;
			}


      if(node.expression?.escapedText === 'baseActions'){
        for (let index = 0; index < innerActions.length; index++) {
          const innerActionItem = innerActions[index];
          actionList.push(modelName ?`${modelName}/${innerActionItem}` : innerActionItem); // 存储完整的action那么
        }
        return;
      }
		});
	}
	return actionList;
}


function getRootActionName(tsOrJsFilePath:string) {
  let actionNameList:any = [];


  const sourceFile = ts.createSourceFile(
		tsOrJsFilePath,
		fs.readFileSync(tsOrJsFilePath).toString(),
		ts.ScriptTarget.ES2015,
		/*setParentNodes */ true
	);


  let varStatementList = sourceFile.statements.filter((astItem:any)=>{
    return astItem.kind === ts.SyntaxKind.VariableStatement;
  });

  let rootStore:any = varStatementList.filter((astItem:any)=>{
    return astItem.getText().includes('actions');
  })[0];

  let actionObj = rootStore?.declarationList?.declarations[0]?.initializer?.arguments[0]?.properties?.filter((astItem:any) => {
    return astItem.name.escapedText === 'actions';
  })[0];


  actionObj.initializer.properties.forEach((node:any) => {
    if(node.kind === ts.SyntaxKind.SpreadAssignment && node.getText() === '...baseActions'){
      for (let index = 0; index < innerActions.length; index++) {
        const innerActionItem = innerActions[index];
        actionNameList.push(innerActionItem);
      }
      return; 
    }
    if(node.kind ===  ts.SyntaxKind.ShorthandPropertyAssignment){
      actionNameList.push(node.name.escapedText);
      return; 
    }

    if(node.kind ===  ts.SyntaxKind.MethodDeclaration){
      actionNameList.push(node.name.escapedText);
      return; 
    }

    if(node.kind === ts.SyntaxKind.PropertyAssignment && node.initializer.kind === ts.SyntaxKind.FunctionExpression){
      actionNameList.push(node.name.escapedText);
    }
  });


  console.log("🚀 ~ file: testAst.ts:19 ~ getRootActionName ~ actionNameList", actionNameList);

  return actionNameList;

}

function getApiUrlNameList(absPath:string){
// src/constant/sourceMap.ts
  // 使用新的 API 键名提取工具函数
  return extractUrlApiKeyFromFile(absPath);
}


// 为action命令提供补全项
function provideCompletionItemsForActionCommand(document:TextDocument, position:Position, token:CancellationToken, context:CompletionContext){

	// 获取当前位置的文本
	const word        	= document.getText(document.getWordRangeAtPosition(position));
	// 获取当前文档的语言ID
	const languageId	= document.languageId;



	console.log("🚀 ~ file: extension.ts:65 ~ provideCompletionItems ~ word", word);

	

	// 创建一个补全项
	let xLogicActionSnippet = new vscode.CompletionItem({
		label:'xLogic', 
		description: "xLogic生成的快捷方式",
	});


	// 根据语言ID确定store的名称
	let storeName = languageId === 'vue' ? 'store' : 'context';
	// 设置补全项的类型为代码片段
	xLogicActionSnippet.kind = vscode.CompletionItemKind.Snippet;
	// 设置补全项的插入文本
	xLogicActionSnippet.insertText = new vscode.SnippetString(storeName+".dispatch('${1|"+xlogicActionList.join(',')+"|}',{${2|"+actionParams+"|}:${3},${4|"+actionParams+"|}:${5}})");
	console.log("🚀 ~ file: extension.ts:72 ~ provideCompletionItems ~ xLogicActionSnippet", xLogicActionSnippet);
	// 返回补全项
	return [
		xLogicActionSnippet
	];
}


// 为actionName提供补全项
function provideCompletionItemsForActionName(document:TextDocument, position:Position, token:CancellationToken, context:CompletionContext){

	// 获取当前位置的文本
	const word        	= document.getText(document.getWordRangeAtPosition(position));
	// 获取当前文档的语言ID
	const languageId	= document.languageId;


	console.log("🚀 ~ file: extension.ts:65 ~ provideCompletionItems ~ word", word);

	// 创建一个补全项
	let xLogicActionNameSnippet = new vscode.CompletionItem({
		label:'xActionName', 
		description: "显示完整的actionsName",
	});



	// 设置补全项的类型为代码片段
	xLogicActionNameSnippet.kind = vscode.CompletionItemKind.Snippet;
	// 设置补全项的插入文本为xlogicActionList的逗号分隔字符串
	xLogicActionNameSnippet.insertText = new vscode.SnippetString("${1|"+xlogicActionList.join(',')+"|}");
	console.log("🚀 ~ file: extension.ts:72 ~ provideCompletionItems ~ xLogicActionNameSnippet", xLogicActionNameSnippet);
	// 返回补全项数组
	return [
		xLogicActionNameSnippet
	];
}


// 为apiUrlName提供补全项
function provideCompletionItemsForApiUrlKey(document:TextDocument, position:Position, token:CancellationToken, context:CompletionContext){
	// 获取当前位置的文本
	const word = document.getText(document.getWordRangeAtPosition(position));
	// 获取当前文档的语言ID
	const languageId = document.languageId;

	console.log("🚀 ~ file: extension.ts:xx ~ provideCompletionItemsForApiUrlKey ~ word", word);

	// 创建一个补全项
	let apiUrlKeySnippet = new vscode.CompletionItem({
		label: 'apiUrlKey',
		description: "显示完整的apiUrlNameList",
	});

	// 设置补全项的类型为代码片段
	apiUrlKeySnippet.kind = vscode.CompletionItemKind.Snippet;

	// 设置补全项的插入文本为apiUrlNameList的逗号分隔字符串，并追加选中的值
	apiUrlKeySnippet.insertText = new vscode.SnippetString("apiUrlKey:'${1|" + apiUrlNameList.join(',') + "|}',");

	console.log("🚀 ~ file: extension.ts:xx ~ provideCompletionItemsForApiUrlKey ~ apiUrlKeySnippet", apiUrlKeySnippet);

	// 返回补全项数组
	return [
		apiUrlKeySnippet
	];

}



function resolveCompletionItem(){
	return null;
}

// 定义一个函数，用于生成actionMapInfo
function makeActionMapInfo(projectRootPath:string){
	// 将项目根路径转换为store模块的路径
	let storePath = convertPath(projectRootPath+'/src/store/modules/',isWindows?'win32':'posix');
  // 将项目根路径转换为store的index.ts路径
  let storeIndexTs = convertPath(projectRootPath+'/src/store/index.ts',isWindows?'win32':'posix');
  // 将项目根路径转换为store的index.js路径
  let storeIndexJs = convertPath(projectRootPath+'/src/store/index.js',isWindows?'win32':'posix');
  // 将项目根路径转换为constant/sourceMap.ts路径
  let apiKeyFilePath = convertPath(projectRootPath+'/src/constant/sourceMap.ts',isWindows?'win32':'posix');
	// 读取store模块文件夹
	fs.readdir(storePath,function(error:any,files:string[]){
		if(error) {
			console.error("读取文件夹错误!!!!!");
			return ;
		}

    // 判断store的index.ts文件是否存在
    fs.access(storeIndexTs,fs.constants.F_OK,(error:any)=>{
      if (error) {return;}
      // 获取store的index.ts中的action名称
      let al = getRootActionName(storeIndexTs);
      // 将action名称添加到xlogicActionList中
      xlogicActionList.push(...al);
    });

    // 判断store的index.js文件是否存在
    fs.access(storeIndexJs,fs.constants.F_OK,(error:any)=>{
        if (error) {return;}
        // 获取store的index.js中的action名称
        let al = getRootActionName(storeIndexJs);
        // 将action名称添加到xlogicActionList中
        xlogicActionList.push(...al);
    });

		// 遍历文件夹中的文件
		files.forEach((fileName:string) => {
      // 将文件名按照.分割，获取文件名和文件类型
      let [modelName,fileType] = fileName.split('.');
			// 判断文件类型是否可以读取
			if(!canReadFileTypes.includes(fileType)){
				return ;
			}

			// 获取模块的action名称
			let al = getModuleActionName(fileName,storePath,modelName);
			// 将action名称添加到xlogicActionList中
			xlogicActionList.push(...al);
		});
	});

  // 获取apiUrlNameList
  apiUrlNameList = getApiUrlNameList(apiKeyFilePath);
  console.log("🚀 ~ makeActionMapInfo ~ apiUrlNameMap:", apiUrlNameList);
  

}

// 导出一个activate函数，接收一个ExtensionContext参数
export function activate(context:ExtensionContext) {
	// 打印日志，输出当前工作区的文件夹
	console.log('activate into ...............into------',vscode.workspace.workspaceFolders);
	// 重置一下
	xlogicActionList = [];
	// 如果当前工作区没有文件夹，则返回
	if(!vscode.workspace.workspaceFolders) {
		return;
	}

	// 获取当前工作区的根路径
	let projectRootPath:any = vscode.workspace.workspaceFolders[0]?.uri.path;

	// 如果是Windows系统，则去掉路径的第一个字符
	if(isWindows){
		projectRootPath = drop(1,projectRootPath);
	}

	// 根据根路径生成actionMapInfo
	makeActionMapInfo(projectRootPath);

	// 注册一个命令，用于重新加载
	let reloadActionCommad = vscode.commands.registerCommand('vscode-extension-xlogic-tips.actionreload', () => {

		// 如果当前工作区没有文件夹，则返回
		if(!vscode.workspace.workspaceFolders) {
			return;
		}
		xlogicActionList = [];
    // 获取配置中的innerActions，并分割成数组
    innerActions= (vscode.workspace.getConfiguration('xlogicTips').get('innerActions') as string).split(',');

		// 获取当前工作区的根路径
		let projectRootPath:any = vscode.workspace.workspaceFolders[0]?.uri.path;

		// 如果是Windows系统，则去掉路径的第一个字符
		if(isWindows){
			projectRootPath = drop(1,projectRootPath);
		}

		// 根据根路径生成actionMapInfo
		makeActionMapInfo(projectRootPath);
		// 显示重新加载成功的消息
		vscode.window.showInformationMessage('重新加载成功');
	});

	// 注册一个命令，用于测试提取 JS 文件中的对象键名
	let testExtractKeysCommand = vscode.commands.registerCommand('vscode-extension-xlogic-tips.testExtractKeys', () => {
		// 如果当前工作区没有文件夹，则返回
		if(!vscode.workspace.workspaceFolders) {
			vscode.window.showErrorMessage('请先打开一个工作区');
			return;
		}

		// 获取当前工作区的根路径
		let projectRootPath:any = vscode.workspace.workspaceFolders[0]?.uri.path;

		// 如果是Windows系统，则去掉路径的第一个字符
		if(isWindows){
			projectRootPath = drop(1,projectRootPath);
		}

		// 测试文件路径（包含函数定义的文件）
		const testFilePath = convertPath(projectRootPath + '/test-with-functions.js', isWindows ? 'win32' : 'posix');
		
		// 使用优化的 API 端点提取函数（包含点号验证）
		const extractedKeys = extractAPIEndpointKeys(testFilePath);
		
		// 显示结果
		if (extractedKeys.length > 0) {
			vscode.window.showInformationMessage(`提取到 ${extractedKeys.length} 个有效的 API 端点键名（包含点号）: ${extractedKeys.slice(0, 3).join(', ')}${extractedKeys.length > 3 ? '...' : ''}`);
			console.log('提取到的所有有效 API 端点键名:', extractedKeys);
		} else {
			vscode.window.showWarningMessage('未能提取到任何有效的 API 端点键名');
		}
	});


	// 将命令添加到订阅中
	context.subscriptions.push(reloadActionCommad);
	context.subscriptions.push(testExtractKeysCommand);
	// 注册一个CompletionItemProvider，用于提供action命令的补全项
	context.subscriptions.push(vscode.languages.registerCompletionItemProvider(languagesList, {
      provideCompletionItems:provideCompletionItemsForActionCommand,
      resolveCompletionItem
    }, 'x')
  );
  // 注册一个CompletionItemProvider，用于提供action名称的补全项
  context.subscriptions.push(vscode.languages.registerCompletionItemProvider(languagesList, {
    provideCompletionItems:provideCompletionItemsForActionName,
    resolveCompletionItem
   }, 'x')
  );


  context.subscriptions.push(vscode.languages.registerCompletionItemProvider(languagesList, {
    provideCompletionItems:provideCompletionItemsForApiUrlKey,
    resolveCompletionItem
  }, 'apiUrlKey:'));

}

// This method is called when your extension is deactivated
export function deactivate() {}



/*
  管理地址 https://marketplace.visualstudio.com/manage/publishers/milesfu
*/